﻿using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace SupplyChain.Infrastructure.Interface
{
    public interface IBaseRepository<T>
    {
        #region Add
        /// <summary>
        /// 增加单条数据
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <returns>操作是否成功</returns>
        public Task<bool> AddAsync(T model);

        /// <summary>
        /// 增加多条数据
        /// </summary>
        /// <param name="list">实体集合</param>
        /// <returns>操作是否成功</returns>
        public Task<bool> AddRangeAsync(List<T> list);

        /// <summary>
        /// 添加单条数据，并返回 自增列
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <returns></returns>
        public Task<bool> AddReturnIdentityAsync(T model);

        /// <summary>
        /// 增加单条数据 ，并返回 实体
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <returns></returns>
        public Task<T> AddReturnEntityAsync(T model);

        /// <summary>
        /// 只添加指定列
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <param name="columns">指定要添加的列</param>
        /// <returns></returns>
        public Task<bool> AddColumnsAsync(T model, params string[] columns);

        /// <summary>
        /// 不插入指定列
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <param name="IgnoreColumns">要忽略的列</param>
        /// <returns></returns>
        public Task<bool> AddColumnsByIgnoreColumnsAsync(T model, params string[] IgnoreColumns);

        #endregion

        #region Delete

        /// <summary>
        /// 根据主键删除，并返回操作是否成功
        /// </summary>
        /// <typeparam name="S">主键的类型</typeparam>
        /// <param name="key">主键</param>
        /// <returns></returns>
        public Task<bool> DeleteAsync<S>(S key);

        /// <summary>
        /// 根据主键删除，并返回操作是否成功
        /// </summary>
        /// <typeparam name="S">主键类型</typeparam>
        /// <param name="keys">主键</param>
        /// <returns></returns>
        public Task<bool> DeleteRangeAsync<S>(params S[] keys);

        /// <summary>
        /// 根据条件删除，并返回操作是否成功
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        public Task<bool> DeleteWhereAsync(Expression<Func<T, bool>> where);

        #endregion

        #region Update

        /// <summary>
        /// 根据主键更新 ，返回操作是否成功
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public Task<bool> UpdateAsync(T model);

        /// <summary>
        /// 根据主键更新，返回操作是否成功
        /// </summary>
        /// <param name="list">实体集合</param>
        /// <returns></returns>
        public Task<bool> UpdateRangeAsync(List<T> list);

        /// <summary>
        /// 根据指定 列条件 更新 ，并返回操作是否成功
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <param name="expression">列条件 例如： t=>t.id>5 </param>
        public Task<bool> UpdateAsync(T model, Expression<Func<T, object>> expression);

        /// <summary>
        /// 根据主键，更新指定列,返回操作是否成功
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <param name="columns">要更新的列</param>
        /// <returns></returns>
        public Task<bool> UpdateColumnsAsync(T model, params string[] columns);

        /// <summary>
        /// 根据主键 ， 忽略更新指定列，返回操作是否成功
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <param name="columns">不更新的 忽略列</param>
        /// <returns></returns>
        public Task<bool> UpdateColumnsByIgnoreColumnsAsync(T model, params string[] columns);

        /// <summary>
        /// 根据主键更新 列
        /// </summary>
        /// <param name="model">实体对象</param>
        /// <param name="ignoreAllNullColumns">是否 NULL的列不更新</param>
        /// <param name="isOffIdentity">是否忽略 自增列</param>
        /// <param name="ignoreAllDefaultValue">是否 忽略默认值列</param>
        /// <returns></returns>
        public Task<bool> UpdateNotNullColumnsAsync(T model, bool ignoreAllNullColumns, bool isOffIdentity = false, bool ignoreAllDefaultValue = false);

        #endregion

        #region Query

        /// <summary>
        /// 查询所有数据
        /// </summary>
        /// <returns></returns>
        public Task<List<T>> GetAllAsync(bool isOrderBy = false, Expression<Func<T, object>> orderBy = null, OrderByType orderByType = OrderByType.Asc);

        /// <summary>
        /// 取前 num 条数据
        /// </summary>
        /// <param name="num">取前几条</param>
        /// <returns></returns>
        public Task<List<T>> GetTakeListAsync(int num, bool isOrderBy = false, Expression<Func<T, object>> orderBy = null, OrderByType orderByType = OrderByType.Asc);

        /// <summary>
        /// 获取符合条件的前 num 条数据
        /// </summary>
        /// <param name="where">条件</param>
        /// <param name="num">取前几条</param>
        /// <returns></returns> 
        public Task<List<T>> GetTakeListAsync(Expression<Func<T, bool>> where, int num, bool isOrderBy = false, Expression<Func<T, object>> orderBy = null, OrderByType orderByType = OrderByType.Asc);

        /// <summary>
        /// 根据主键查询
        /// </summary>
        /// <param name="pkValue">主键</param>
        /// <returns></returns>
        public Task<T> GetByPrimaryKeyAsync(object pkValue);

        /// <summary>
        /// 根据条件获取 单条数据 
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        public Task<T> GetFirstOrDefaultAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 根据条件 查询
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        public Task<List<T>> GetByWhereAsync(Expression<Func<T, bool>> where, bool isOrderBy = false, Expression<Func<T, object>> orderBy = null, OrderByType orderByType = OrderByType.Asc);

        /// <summary>
        /// 查询 指定列的值 在 start至end 之间的数据
        /// </summary>
        /// <param name="value">指定类</param>
        /// <param name="start">开始</param>
        /// <param name="end">结束</param>
        /// <returns></returns>
        public Task<List<T>> GetByBetweenAsync(object value, object start, object end, bool isOrderBy = false, Expression<Func<T, object>> orderBy = null, OrderByType orderByType = OrderByType.Asc);

        /// <summary>
        /// 判断是否存在这条记录
        /// </summary>
        /// <param name="where">条件</param>
        /// <returns></returns>
        public Task<bool> GetIsAnyAsync(Expression<Func<T, bool>> where);

        /// <summary>
        /// 执行查询sql语句 ，返回数据集
        /// </summary>
        /// <param name="sql">sql语句</param>
        /// <returns></returns>
        public Task<List<T>> GetListBySqlAsync(string sql);

        /// <summary>
        /// 执行非查询sql语句，返回操作是否成功
        /// </summary>
        /// <param name="sql">sql语句</param>
        /// <param name="parameters">参数化</param>
        /// <returns></returns>
        public Task<bool> ExecuteCommandSqlAsync(string sql, params SugarParameter[] parameters);

        /// <summary>
        /// 执行查询sql语句，返回查询的结果集
        /// </summary>
        /// <param name="sql">sql语句</param>
        /// <param name="parameters">参数化</param>
        /// <returns></returns>
        public Task<List<T>> GetListBySqlQueryAsync(string sql, params SugarParameter[] parameters);

        /// <summary>
        /// 执行查询sql语句，返回 第一行第一列
        /// </summary>
        /// <param name="sql">sql语句</param>
        /// <param name="parameters">参数化</param>
        /// <returns></returns>
        public Task<object> GetScalarAsync(string sql, params SugarParameter[] parameters);

        #endregion
    }
}
